package com.gujiangbo.application.common.fc;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.gujiangbo.application.common.fc.info.FlowControlInfo;
import com.gujiangbo.application.config.CommonZKConfig;

public class FlowControlManage {
	private static Log debugLog = LogFactory.getLog(FlowControlManage.class);
	@Autowired
	private CommonZKConfig commonzkConfig;
	private Map<String, Semaphore> Semaphores;

	public void init() {
		debugLog.info("========== init FlowControlManage begin ==========");
		this.Semaphores = new ConcurrentHashMap();
		List<FlowControlInfo> flowList = getFlowControlInfo();
		if ((flowList != null) && (flowList.size() > 0)) {
			for (FlowControlInfo flowcontrol : flowList) {
				if (flowcontrol != null) {
					Semaphore conSem = createSemaphore(flowcontrol);
					this.Semaphores.put(flowcontrol.getMethod(), conSem);
				}
			}
		}
		debugLog.info("========== init FlowControlManage end ==========");
	}

	public boolean getSignPoint(String className) {
		Semaphore conSem = null;
		conSem = (Semaphore) this.Semaphores.get(className);
		if (conSem == null) {
			return true;
		}
		return conSem.tryAcquire();
	}

	private Semaphore createSemaphore(FlowControlInfo flowcontrol) {
		if (StringUtils.isBlank(flowcontrol.getLimtCount())) {
			flowcontrol.setLimtCount(this.commonzkConfig.getFc_default_limtCount());
		}
		if (StringUtils.isBlank(flowcontrol.getTaskTime())) {
			flowcontrol.setTaskTime(this.commonzkConfig.getFc_default_taskTime());
		}
		int limtCount = Integer.valueOf(flowcontrol.getLimtCount()).intValue();
		int taskTime = Integer.valueOf(flowcontrol.getTaskTime()).intValue();
		if (limtCount <= 0) {
			limtCount = Integer.valueOf(this.commonzkConfig.getFc_default_limtCount()).intValue();
		}
		if (taskTime <= 0) {
			taskTime = Integer.valueOf(this.commonzkConfig.getFc_default_taskTime()).intValue();
		}
		Semaphore conSem = new Semaphore(limtCount);

		taskSignPoint(conSem, taskTime, limtCount);
		return conSem;
	}

	private void taskSignPoint(Semaphore conSem, int taskTime, int limtCount) {
		CleanSemaphoreTask task = new CleanSemaphoreTask();
		task.setConSem(conSem);
		task.setLimtCount(limtCount);
		task.setTaskTime(taskTime);
		task.start();
	}

	private List<FlowControlInfo> getFlowControlInfo() {
		List<FlowControlInfo> list = new LinkedList();

		String conf = this.commonzkConfig.getFlow_control_conf();
		if (StringUtils.isNotBlank(conf)) {
			String[] arrays = conf.split(",", -2);
			if ((arrays != null) && (arrays.length > 0)) {
				String[] arrayOfString1;
				int j = (arrayOfString1 = arrays).length;
				for (int i = 0; i < j; i++) {
					String methodconf = arrayOfString1[i];
					if (!StringUtils.isBlank(methodconf)) {
						String[] methodArrays = methodconf.split("_", -2);
						FlowControlInfo info = new FlowControlInfo();
						info.setMethod(methodArrays[0]);
						if (methodArrays.length != 1) {
							info.setLimtCount(methodArrays[1]);
							info.setTaskTime(methodArrays[2]);
						}
						list.add(info);
					}
				}
			}
		}
		return list;
	}
}